<?php
abstract class Shuffler_UnitTestCase extends PHPUnit_Framework_TestCase
{
    
    protected function pass()
    {
        $this->assertTrue( true );
    }
    
    function getMapper( $model )
    {
        return Shuffler_Factory::getInstance()->getMapper( $model );
    }
    
    public function assertStringContains( $needle, $haystack )
    {
        if( strpos( $haystack, $needle ) === false )
        {
            $this->fail( 'String [' . $haystack . '] should contain [' . $needle . ']' );
        }
        else
        {
            $this->pass();
        }
    }
    
    public function assertInArray( $needle, array $haystack, $msg = null )
    {
        if( is_null( $msg ) && is_string( $needle ) || is_numeric( $needle ) )
        {
            $msg = $needle . ' should be in array ' . implode( ', ', $haystack );
        }
        $this->assertTrue( in_array( $needle, $haystack ), $msg );
    }
    
    public function assertNotInArray( $needle, array $haystack, $msg = null )
    {
        if( is_null( $msg ) && is_string( $needle ) || is_numeric( $needle ) )
        {
            $msg = $needle . ' should be in array ' . implode( ', ', $haystack );
        }
        $this->assertFalse( in_array( $needle, $haystack ), $msg );
    }
    
    public function assertCollectionContains( Shuffler_Model $needle, Shuffler_Collection $collection )
    {
        if( !( $collection instanceof Shuffler_Collection ) )
        {
            throw new Exception( 'collection must be instance of Shuffler_Collection' );
        }
        $this->assertTrue( $collection->contains( $needle ) );
    }
    
    public function assertCollectionSame( Shuffler_Collection $left, Shuffler_Collection $right )
    {
        if( $left->contains( $right ) && $right->contains( $left ) )
        {
            return $this->pass();
        }
        ob_start();
        echo "Expected\n";
        print_r( $left->toIdArray() );
        echo "\n\nActual\n";
        print_r( $right->toIdArray() );
        $msg=  ob_get_clean();
        $this->fail( $msg );
    }
    
    public function assertCollectionNotContains( Shuffler_Model $needle, Shuffler_Collection $collection )
    {
        if( !( $collection instanceof Shuffler_Collection ) )
        {
            throw new Exception( 'collection must be instance of Shuffler_Collection' );
        }
        $this->assertFalse( $collection->contains( $needle ) );
    }
    
    /**
    * Assert that two models are the same entity
    * 
    * @param Shuffler_Model $a expected
    * @param Shuffler_Model $b actual
    * @param string $message
    * @param boolean $ignoreClass set to true if comparing mocks
    */
    public function assertSameModel( Shuffler_Model $a, Shuffler_Model $b, $message = null, $ignoreClass = false )
    {
        if( $ignoreClass )
        {
            if( $a->getId() == 0 )
            {
                return $this->assertFalse();
            }
            return $this->assertTrue( $a->getId() == $b->getId() );
        }
        if( !( $a instanceof Shuffler_Model ) )
        {
            $this->fail( 'a must be Shuffler_Model' );
            return;
        }
        if( !( $b instanceof Shuffler_Model ) )
        {
            $this->fail( 'b must be Shuffler_Model' );
            return;
        }
        if( is_null( $message ) )
        {
            $message = 'objects must be identical, ' . get_class( $a ) . ' ' . (int)$a->getId() . ' ' . get_class( $b ) . ' ' . (int)$b->getId();
        }
        $this->assertTrue( $a->equals( $b ), $message );
    }
    
    public function getAdapterWithReadReturnValue( array $value )
    {
        
        $stmt = $this->getMock( 'Zend_Db_Statement_Mysqli', array( 'fetchAll' ), array(), '', false );
        $stmt
            ->expects( $this->any() )
            ->method( 'fetchAll' )
            ->will( $this->returnValue( $value ) );
        
        $select = $this->getMock( 'Zend_Db_Select', array( 'from', 'where', 'joinleft' ), array(), '', false );
        $select
            ->expects( $this->any() )
            ->method( 'from' )
            ->will( $this->returnValue( $select ) );
        $select
            ->expects( $this->any() )
            ->method( 'where' )
            ->will( $this->returnValue( $select ) );
        $select
            ->expects( $this->any() )
            ->method( 'joinLeft' )
            ->will( $this->returnValue( $select ) );
            
        /**
        * Adapter will return  stmt & select for query() and select() respectively
        */
        $adapter = $this->getMock( 'Shuffler_Mapper_Adapter_ZendDb' ); 
        $adapter
            ->expects( $this->any() )
            ->method( 'query' )
            ->will( $this->returnValue( $stmt ) );
        $adapter
            ->expects( $this->any() )
            ->method( 'select' )
            ->will( $this->returnValue( $select ) );
        
        return $adapter;
    }
    
    protected function getMockAdapter()
    {
        return $this->getMock( 'Shuffler_Mapper_Adapter_ZendDb', array(), array( null, null ) );
    }  
    
    function tearDown()
    {
        Shuffler_Factory::getInstance()->clearIdentityMaps();
    }
    
    protected function assertIsA( $obj, $class )
    {
        if( $obj instanceof $class )
        {
            $this->pass( 'object is ' . $class );
        }
        else
        {
            $this->fail( 'object is ' . ( gettype( $obj ) == 'object' ? get_class( $obj ) : gettype( $obj ) ) . ', ' . $class . ' expected' ); 
        }
    }
    
}